package com.msk.third.service;

import com.alibaba.fastjson2.JSONObject;
import com.msk.common.constant.Constants;
import com.msk.common.core.domain.R;
import com.msk.common.core.redis.RedisCache;
import com.msk.common.utils.StringUtils;
import com.msk.common.utils.http.HttpRequestUtil;
import com.msk.common.wechatV3.config.WxPayV3Config;
import com.msk.sys.utils.DictMskUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @desc: 微信小程序服务
 * @author: zlf
 * @date: 2022-02-28 19:25
 **/
@Service
public class MiniProgramService {

    private static final Logger logger = LoggerFactory.getLogger(MiniProgramService.class);

    @Autowired
    private WxPayV3Config wxPayV3Config;

    @Autowired
    private RedisCache redisService;

    /**
     * 获取小程序访问凭证
     * @return
     */
    public R<JSONObject> getMpAccessToken() {
        if (redisService.keyIsExists(Constants.SYS_CONFIG_KEY + "mp_access_token")) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("access_token", redisService.getCacheObject(Constants.SYS_CONFIG_KEY + "mp_access_token"));
            return R.appOk(jsonObject);
        }
        String miniAccessTokenUrl = wxPayV3Config.getMiniAccessTokenUrl();
        String miniAppId = wxPayV3Config.getMiniAppId();
        String miniSecretKey = wxPayV3Config.getMiniSecretKey();
        Map<String, String> param = new HashMap<>();
        param.put("grant_type", "client_credential");
        param.put("appid", miniAppId);
        param.put("secret", miniSecretKey);
        //调用获取session_key接口 请求方式get
        String jsonString = HttpRequestUtil.sendGet(miniAccessTokenUrl, param, null);
        if (StringUtils.isNotEmpty(jsonString)) {
            //因为json字符串是大括号包围，所以用JSONObject解析
            JSONObject jsonObject = JSONObject.parseObject(jsonString);
            if (jsonObject.containsKey("access_token")) {
                String accessToken = jsonObject.getString("access_token");
                Integer expiresIn = jsonObject.getIntValue("expires_in");
                redisService.setCacheObject(Constants.SYS_CONFIG_KEY + "mp_access_token", accessToken, expiresIn, TimeUnit.SECONDS);
                return R.appOk(jsonObject);
            } else if (jsonObject.containsKey("errcode") && jsonObject.containsKey("errmsg")) {
                return R.appFail(jsonObject.getIntValue("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return R.appFail(2000,"获取访问凭证失败");
    }

    /**
     * 获取小程序手机号
     * @return
     */
    public R<JSONObject> getMpPhoneNumber(String code) {
        String miniPhoneNumberUrl = wxPayV3Config.getMiniPhoneNumberUrl();
        //这里判断是生产环境正常走获取token方法，测试环境需要从生产环境获取token   生产环境0 测试环境1
        String value = DictMskUtils.getDictValue("生产测试环境切换", "msk_sys_token_url", "1");
        R<JSONObject> jsonObjectResult = null;
        if("0".equals(value)){
            jsonObjectResult = getMpAccessToken();
        }else if("1".equals(value)) {
            jsonObjectResult = getAccessMpToken();
        }
        String accessToken = "";
        if (jsonObjectResult.getCode() == Constants.SUCCESS_APP) {
            accessToken = jsonObjectResult.getData().getString("access_token");
        } else {
            return jsonObjectResult;
        }
        Map<String, String> param = new HashMap<>();
        param.put("code", code);
        miniPhoneNumberUrl += "?access_token=" + accessToken;
        //调用获取session_key接口 请求方式get
        String jsonString = HttpRequestUtil.sendPost(miniPhoneNumberUrl, param, true);
        if (StringUtils.isNotEmpty(jsonString)) {
            //因为json字符串是大括号包围，所以用JSONObject解析
            JSONObject jsonObject = JSONObject.parseObject(jsonString);
            Integer errcode = jsonObject.getIntValue("errcode");
            if (errcode != null && errcode == Constants.SUCCESS_APP) {
                JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
                return R.appOk(phoneInfo);
            } else {
                return R.appFail(jsonObject.getIntValue("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return R.appFail(2000,"获取访问凭证失败");
    }

    /**
     * @description: 获取生产环境的小程序token
     * @author: dz
     * @date: 2022/10/19 19:35
     * @param: [url]
     * @return: java.lang.String
     **/
    public R<JSONObject> getAccessMpToken(){
        //数据字典获取生产url
        String prodUrl = DictMskUtils.getDictValue("生产环境url", "msk_sys_token_url", "");
        String jsonString = HttpRequestUtil.sendPost(prodUrl + "api/mp/miniProgram/getAccessMpToken", new HashMap<>(), true);
        JSONObject jsonObject = JSONObject.parseObject(jsonString);
        logger.info("获取生产环境小程序token:{}",JSONObject.parseObject(jsonObject.getString("data")).get("access_token"));
        JSONObject data = JSONObject.parseObject(jsonObject.getString("data"));
        String access_token = data.getString("access_token");
        if(StringUtils.isEmpty(access_token)){
            return R.appFail(2000,"获取access_token失败");
        }
        return R.appOk(data);
    }

    /**
     * 授权登录获取信息sessionKey
     * @param code
     * @return
     */
    public R<JSONObject> getMpSessionKey(String code) {
        String miniLoginUrl = wxPayV3Config.getMiniLoginUrl();
        String miniAppId = wxPayV3Config.getMiniAppId();
        String miniSecretKey = wxPayV3Config.getMiniSecretKey();
        Map<String, String> param = new HashMap<>();
        param.put("appid", miniAppId);
        param.put("secret", miniSecretKey);
        param.put("js_code", code);
        param.put("grant_type", "authorization_code");
        //调用获取session_key接口 请求方式get
        String jsonString = HttpRequestUtil.sendGet(miniLoginUrl, param, null);
        if (StringUtils.isNotEmpty(jsonString)) {
            //因为json字符串是大括号包围，所以用JSONObject解析
            JSONObject jsonObject = JSONObject.parseObject(jsonString);
            if (jsonObject.containsKey("session_key")) {
                return R.appOk(jsonObject);
            } else if (jsonObject.containsKey("errcode") && jsonObject.containsKey("errmsg")) {
                return R.appFail(jsonObject.getIntValue("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return R.appFail(2000,"授权登录获取信息失败");
    }
}
